1-2 ES规范和模块规范:探寻ECMAScript发展史
ECMAScript 规范
ECMA 是一个国际标准化组织,JavaScript 的标准由该组织制定。其中 ECMA-262 议案定义了 ECMAScript(简称 ES)规范。自 1997 年第一个版本诞生以来,ES 已发展为全球使用最广泛的编程语言之一,广泛应用于浏览器端、服务端(Node.js)和嵌入式应用。
ECMAScript 最初被设计为 Web 脚本语言,用于在浏览器中激活网页并作为基于 Web 的客户端-服务器架构的一部分执行服务器计算。随着使用范围的扩大,ECMAScript 已经超越了简单的脚本编程,现在被广泛应用于许多不同环境和规模下的全方位编程任务,成为一个完整而强大的通用编程语言。
ES 版本演进
| 版本 | 年份 | 关键特性 |
|---|---|---|
| ES5 | 2009 | 严格模式、JSON 对象支持、forEach/map/filter 等高级数组方法 |
| ES6(ES2015) | 2015 | let/const、箭头函数、Promise、模块化(import/export)、解构赋值、类、模板字符串 |
| ES7(ES2016) | 2016 | Array.includes、指数运算符(**) |
| ES8(ES2017) | 2017 | async/await、Object.entries/values |
| ES10(ES2019) | 2019 | Array.flat、Object.fromEntries |
| ES11(ES2020) | 2020 | 可选链(?.)、空值合并运算符(??)、BigInt |
| ES12(ES2021) | 2021 | 逻辑赋值运算符(` |
| ES15(ES2024) | 2024 | 最新版本 |
ES6 是一个重要的分水岭,引入了大量新语法和特性。从 ES2016 开始,ECMA 国际组织决定每年发布一次规范的更新。在国内的语境中,"ES6"通常泛指 ES2015 到 ES2022 期间所有新版本的语法。
可选链与空值合并运算符
// 可选链(Optional Chaining)—— ES2020
const name = user?.profile?.name; // 如果 user 或 profile 为 null/undefined,不会报错
// 空值合并运算符(Nullish Coalescing)—— ES2020
const value = input ?? 'default'; // 仅在 input 为 null 或 undefined 时使用默认值
// 与 || 运算符的区别
const a = 0 || 'default'; // 'default'(0 是假值)
const b = 0 ?? 'default'; // 0(0 不是 null/undefined)
const c = '' || 'default'; // 'default'(空字符串是假值)
const d = '' ?? 'default'; // ''(空字符串不是 null/undefined)
typescript
模块化规范
CommonJS(Node.js 默认规范)
Node.js 诞生时就创建了 CommonJS 规范,使用 require 和 module.exports 进行模块导入导出。这种规范支持同步加载模块,适合服务端环境,但不适合在浏览器中使用。
// 导出
module.exports = { foo, bar };
// 导入
const { foo, bar } = require('./module');
javascript
AMD(浏览器端模块加载规范)
AMD(Asynchronous Module Definition)是为浏览器环境设计的异步模块加载规范,代表库是 RequireJS。它定义了一个 API 来支持异步加载和管理模块。随着浏览器原生支持 ES Module,AMD 已逐渐被淘汰。
UMD(通用模块规范)
UMD(Universal Module Definition)目的是兼容 CommonJS 和 AMD 规范,使同一个库既能在浏览器端运行,也能在 Node.js 端运行。
以 axios 为例,它作为 HTTP 客户端:
- 在 Node.js 端使用
http/https模块发起请求 - 在浏览器端使用
XMLHttpRequest发起请求 - 打包时通过 Rollup 同时输出 ES Module、UMD 和 CommonJS 三种格式
ES Module(ES6 引入)
ES6 正式引入了模块化系统,使用 import 和 export 关键字:
// 导出
export const foo = 'hello';
export default function bar() {}
// 导入
import bar, { foo } from './module';
javascript
ESM 提供的是静态的模块结构,使得工具可以进行更优化的代码分析,例如 Tree Shaking(用于消除无用代码)。主流浏览器(如 Chrome)已原生支持 ES Module,可以在 <script type="module"> 标签中直接使用 import。现代版本的 Node.js 也已增加对 ESM 的支持。
模块规范与 ES 规范的关系
ES5(无模块化)→ 诞生了 CommonJS(Node.js)和 AMD(浏览器)
↓
ES6(引入 ES Module)→ 统一了模块化标准
↓
未来:CommonJS 逐渐向 ES Module 靠拢
text
在 ES6/ES2015 规范之前,JavaScript 并没有官方的模块系统。在这种情况下,CommonJS 和 AMD 这样的模块规范应运而生,它们分别在服务器和浏览器环境下为 JavaScript 提供了模块化的解决方案。然而,这些解决方案并不是 JavaScript 语言本身的一部分,而是通过库或者运行时环境来实现的。
随着 JavaScript 语言的发展和应用的复杂度增加,模块化成为了越来越重要的特性。ESM 的引入,使得 JavaScript 开发者可以使用 import 和 export 关键字来引入和导出模块,而无需依赖任何第三方库。
值得注意的是,虽然 ESM 是 ECMAScript 规范的一部分,但在浏览器和 Node.js 环境中,对 ESM 的支持是逐步实现的。尤其在 Node.js 中,长期以来 CommonJS 仍是主要的模块系统。而在浏览器中,现代浏览器已经广泛支持 ESM,但对于旧版浏览器,仍然需要通过工具如 Babel 或 Webpack 将 ESM 转换为能被这些浏览器理解的代码。
模块化规范是时代产物。随着 ES Module 的成熟和浏览器/Node.js 的支持,CommonJS、AMD、UMD 等规范终将成为历史。但理解它们的区别对于开发库和框架仍然重要——工程化工具(Webpack、Vite、Rollup)正是为了处理这些规范之间的转换而存在的。
↑